/**
 * 
 */
package gui;

import io.ImportImage;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import game.*;
import gfx.*;

import javax.swing.JFrame;
import javax.swing.WindowConstants;

import network.GameClient;

/**
 * @author Jean-Baptiste BORIC
 *
 */
public class WindowInGame extends JFrame {
	
	private static final long serialVersionUID = 1L;
	
	protected FrameBuffer frameBuffer;
	protected Game game;
	
	private int cameraX;
	private int cameraY;
	
	private int tileWidth;
	private int tileHeight;
	
	protected HashMap<String, GraphicImage> images;
	
	/**
	 * Create a new game viewer
	 * @param width Screen width
	 * @param height Screen height
	 * @param game Game to render
	 * @param images Image collection
	 */
	public WindowInGame(int width, int height, Game game, HashMap<String, GraphicImage> images) {
		super("Student Wars");
		
		this.game = game;
		this.images = images;
		
		this.setSize(width, height);
		
		this.frameBuffer = new FrameBuffer(640, 480);
		this.add(this.frameBuffer);
		this.frameBuffer.setBounds(0, 0, width, height);
	}

	/**
	 * Set camera position
	 * @param x X position
	 * @param y Y position
	 */
	public void setCamera(int x, int y) {
		this.cameraX = x;
		this.cameraY = y;
	}
	
	/**
	 * @return Camera X position
	 */
	public int getCameraX() {
		return cameraX;
	}

	/**
	 * @return Camera Y position
	 */
	public int getCameraY() {
		return cameraY;
	}
	
	/**
	 * Render game
	 */
	public void updateGraphics() {
		if(this.game.isStarted()) {
			
			// Calculate tile width and height
			TileType tileType = game.getTileTypes().get(0); 
			GraphicImage tileImage = this.images.get(tileType.getImage()); 
			tileWidth = tileImage.getWidth() / tileImage.getNbColumns();
			tileHeight = tileImage.getHeight() / tileImage.getNbRows();
			
			this.frameBuffer.pushTransformation(cameraX, cameraY);
			this.renderTileMap();
			this.renderBuildings();
			this.renderUnits();
			this.frameBuffer.popTransformation();
		}
	}
	
	public void swapBuffers() {
		this.frameBuffer.swapBuffers();
	}
	
	//
	// Rendering functions
	//
	
	private void renderTileMap() {
		Map map = this.game.getMap();
		
		GraphicSprite sprite = new GraphicSprite(0, 0, 0, null);
		GraphicImage image = null;
		ArrayList< TileType > tileTypes = this.game.getTileTypes();
		
		for(int y = 0; y < map.getHeight(); y++) {
			for(int x = 0; x < map.getWidth(); x++) {
				int tile = map.getTile(x, y);
				String imageName = tileTypes.get(tile).getImage();
				
				image = this.images.get(imageName);

				sprite.setCoordinates(x*image.getWidth()/image.getNbColumns(),
									  y*image.getHeight()/image.getNbRows());
				sprite.setImage(image);
				
				frameBuffer.drawSprite(sprite);
			}
		}
	}
	
	private void renderBuildings() {
		Map map = this.game.getMap();
		
		GraphicSprite sprite = new GraphicSprite(0, 0, 0, null);
		GraphicImage image = null;

		for(Building b : map.getBuildings()) {
			// Get player to draw correct color
			int playerID = 0;
			Player p = b.getPlayer();
			if(p != null) {
				// Grey "player" is in position 0
				playerID = this.game.getPlayers().indexOf(p) + 1;
			}
			String imageName = b.getType().getImage(playerID);
			
			image = this.images.get(imageName);
			sprite.setCoordinates(b.getX()*tileWidth,
								  b.getY()*tileHeight);
			sprite.setImage(image);
			
			frameBuffer.drawSprite(sprite);
		}
	}
	
	private void renderUnits() {
		Map map = this.game.getMap();
		
		GraphicSprite sprite = new GraphicSprite(0, 0, 0, null);
		GraphicImage image = null;
		
		for(Unit u : map.getUnits()) {
			// Get player to draw correct color
			Player p = u.getPlayer();
			int playerID = 0;
			if(u.isActive()) {
				playerID = this.game.getPlayers().indexOf(p) + 1;
			}

			String imageName = u.getType().getImage(playerID);
			image = this.images.get(imageName);
			
			sprite.setCoordinates(u.getX()*tileWidth,
								  u.getY()*tileHeight);
			sprite.setImage(image);
			frameBuffer.drawSprite(sprite);
		}
	}

	/**
	 * Test function for WindowInGame
	 * @param args Ignored
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket(InetAddress.getByName("localhost"), 34123);
		GameClient client = new GameClient(s);
		ImportImage importImages = new ImportImage(new FileInputStream("data/database/image.tsv"));
		HashMap<String, GraphicImage> images = importImages.read();
		
		WindowInGame w = new WindowInGame(640, 480, client, images);
		w.setVisible(true);
		w.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

		int count = 0;
		while(true) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			count = (count + 1) % 256;
			client.pumpCommmands();
			w.updateGraphics();
			w.swapBuffers();
			w.setCamera(count, 0);
		}
	}
}
